const pathToRegexp = require('path-to-regexp');

export type AuthItem = string;

export type RouterItemBase = {
  // authority: string[];
  access: string;
  path: string;
};

export type AuthCodesItem = {
  authCodes?: EnumOperCode[];
};

const authItemListTarnsCodeList = (authItemList: AuthItem[]): string[] => {
  return authItemList.map((item) => item);
};

const dfsCheckPath = (routerCache: RouterItemBase[], path: string, childKey: string): boolean => {
  return (
    routerCache &&
    routerCache.some((router) => {
      if (pathToRegexp(router.path).exec(path)) {
        return true;
      }
      return dfsCheckPath(router[childKey], path, childKey);
    })
  );
};

export class AuthSdk {
  getCodePromise: () => Promise<AuthItem[]>;
  authItemList: AuthItem[] = [];
  codeList: string[] = [];
  childKey: string = 'children';
  able: boolean = true;
  routerCache: RouterItemBase[] = [];
  routerInited = false;

  constructor(getCodePromise: () => Promise<AuthItem[]>) {
    this.getCodePromise = getCodePromise;
  }

  private async getAuthItemList() {
    if (localStorage.getItem('AuthorizationToken')) {
      this.authItemList = await this.getCodePromise();
    }
    this.codeList = authItemListTarnsCodeList(this.authItemList);
  }

  public async start() {
    await this.getAuthItemList();
  }

  public setAble(_able: boolean) {
    this.able = _able;
  }

  public getAble() {
    return this.able;
  }

  public getCodeList() {
    return this.codeList;
  }

  public setChildKey(_key: string) {
    this.childKey = _key;
  }

  public routerFilter<T extends RouterItemBase>(router: T[]): T[] {
    if (!this.able) {
      this.routerCache = router;
      return this.routerCache as T[];
    }
    this.routerCache = router
      .filter((item) => {
        const markCode = item.access;
        return this.codeList.includes(`${markCode}_VIEW`) || markCode === 'global';
      })
      .map((item) => {
        if (item[this.childKey]) {
          return { ...item, [this.childKey]: this.routerFilter(item[this.childKey]) };
        }
        return item;
      });
    return this.routerCache as T[];
  }

  public btnCheck(pageCode: EnumModuleCode) {
    return (operCode: EnumOperCode, authCodes?: EnumOperCode[]) => {
      if (!this.able) {
        return true;
      }
      if (this.codeList.includes(`${pageCode}_${operCode}`)) {
        if (!authCodes || authCodes.includes(operCode)) {
          return true;
        }
      }
      return false;
    };
  }

  public checkPathAuth(path: string) {
    if (!this.able) {
      return true;
    }
    return dfsCheckPath(this.routerCache, path, this.childKey);
  }
}

// // page的枚举类型
// export enum EnumModuleCode {
//   CONTENT = 'CONTENT',
//   SLEF = 'SLEF',
//   AUTH = 'AUTH',
//   BRAND = 'BRAND',
//   COPYRIGHT = 'COPYRIGHT',
//   SONG = 'SONG',
//   ENTITLEMENT = 'ENTITLEMENT',
//   SONGMATCH = 'SONGMATCH',
//   USER = 'USER',
//   PROJECT = 'PROJECT',
// }

// // 操作的枚举类型
// export enum EnumOperCode {
//   TREE = 'TREE', // 特殊的不管
//   SHARE = 'SHARE',
//   DOWNLOAD = 'DOWNLOAD',
//   EDIT = 'EDIT',
//   VIEW = 'VIEW',
//   ALL_VIEW = 'ALL_VIEW',
// }

// page的枚举类型
export enum EnumModuleCode {
  CONTENT = 'CONTENT',
  CREATE_USER_NAME = 'CREATE_USER_NAME',
}

// 操作的枚举类型
export enum EnumOperCode {
  PRODUCER = 'PRODUCER', // 特殊的不管
  FRESH = 'FRESH',
  MUSICIAN = 'MUSICIAN',
  KGE = 'KGE',
  CDMUSICIAN = 'CDMUSICIAN',
  SHOW = 'SHOW',
  ALL = 'ALL',
  SELF = 'SELF',
}
